package com.misty.auth.config;


import com.misty.auth.filter.LoginFilter;
import com.misty.auth.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsUtils;

@Configuration
@EnableWebSecurity
@ComponentScan({"com.misty.auth","com.misty.common"})
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired(required = false)
    private UserServiceImpl userDetailsService;

    @Autowired(required = false)
    private LoginFilter loginFilter;

    @Autowired
    private IgnoreUrlsConfig ignoreUrlsConfig;

    @Autowired
    MyAccessDeniedHandler myAccessDeniedHandler;

    @Autowired
    MyAuthenticationEnryPoint myAuthenticationEnryPoint;


    @Override
    protected void configure(HttpSecurity http) throws Exception {

        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
                .authorizeRequests();
        for (String url : ignoreUrlsConfig.getUrls()) {
            registry.antMatchers(url).permitAll();
        }

        registry.and()
                .authorizeRequests()
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                .anyRequest()
                .authenticated()
                // 关闭跨站请求防护及不使用session
                .and()
                .csrf()
                .disable()
                //禁用seesion
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                //跨域
                .and()
                .cors()
                // 自定义权限拒绝处理类
                .and()
                .exceptionHandling()
                .accessDeniedHandler(myAccessDeniedHandler)
                .authenticationEntryPoint(myAuthenticationEnryPoint)
                // 自定义权限拦截器JWT过滤器
                .and()
                .addFilterBefore(loginFilter, UsernamePasswordAuthenticationFilter.class)
//                .addFilterBefore(new LoginFilter(), UsernamePasswordAuthenticationFilter.class)
                .headers().frameOptions().sameOrigin();

//        http.authorizeRequests()
//                // 允许前端跨域联调
//                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
//                // 登录、注册接口肯定是不需要认证的
////                .antMatchers("/files","/files/**","/chatroomserver/**").permitAll()
////                .antMatchers("/login", "/register","/test").permitAll()
////                .antMatchers("/fore/comment/{id}").permitAll()
////                .antMatchers("/fore","/fore/**","/fore/**/**").permitAll()
//                .antMatchers("/files/upload").authenticated()
//                .antMatchers("/fore/comment/**","/fore/publish").authenticated()
//                // 这里意思是其它所有接口需要认证才能访问
//                .anyRequest().authenticated()
                // 指定认证错误处理器
//                .and().exceptionHandling().authenticationEntryPoint(new MyAuthenticationEnryPoint());

//        http.addFilterBefore(loginFilter, UsernamePasswordAuthenticationFilter.class);
//
//        http.exceptionHandling()
//                .authenticationEntryPoint(myAuthenticationEnryPoint)
//                .accessDeniedHandler(myAccessDeniedHandler);  
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 指定UserDetailService和加密器
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());

    }



    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/files/**");
    }

    @Bean
    @Override
//    手动认证器
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return  new BCryptPasswordEncoder();
    }
}

